import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from "@angular/forms"
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import * as moment from "moment"

import { MenuManageService } from "./menu-manage.service"
import { HCommonService } from 'src/app/h-common/h-common.service';



export interface TreeNodeInterface {
    key: number;
    title: string;
    icon: string;
    sort: number;
    url: string;
    limitsIdentity: string;
    componentUrl: string;
    outerChain: string;
    cache: string;
    isLook: string;
    createTime: string;
    level?: number;
    expand?: boolean;
    children?: TreeNodeInterface[];
    parent?: TreeNodeInterface;
}
@Component({
    selector: 'app-menu-manage',
    templateUrl: './menu-manage.component.html',
    styleUrls: ['./menu-manage.component.scss']
})
export class MenuManageComponent implements OnInit {
    listOfMapData = <any>[];
    hztreeData = [];
    htreeValue: string = "";
    menuForm: FormGroup;
    isIndeterminate = <boolean>false;
    mapOfExpandedData = [];
    isShowModal = <boolean>false;
    isOkLoading = <boolean>false;
    isAllCheck = <boolean>false;
    private editId: number = -1;
    private deleteIds: number[] = [];
    mapOfCheckedId: { [key: string]: boolean } = {};
    menuType = <number>0;           // 0 目录  1  菜单  2  按钮
    dateRange = [];
    searchKey = <string>"";
    copyData = []
    bornRole = {}

    modalDomBox : any

    constructor(
        private menuManageService: MenuManageService,
        private fb: FormBuilder,
        private modal: NzModalService,
        private commonServie: HCommonService
    ) { }

    async ngOnInit() {
        this.modalDomBox = document.querySelector("#modal_box");
        /* 获取权限 */
        this.bornRole = this.commonServie.getRoles("menu");

        this.menuForm = this.fb.group({
            icon: [null, Validators.required],
            hidden: [false],
            name: [null, Validators.required],
            path: [null, Validators.required],
            pid: [null],
            sort: [null, Validators.required],
            permission: [null],

            iframe: [false],
            cache: [false],
            component: [null],
        })
        await this.getList();
        this.initMapOfExpandedData();
    }

    handleHtree(ev) {

    }
    initHtree(data) {
        const _tempArr = data;
        if (_tempArr.length != 0) {
            for (let i = 0; i < _tempArr.length; i++) {
                let _item = _tempArr[i];
                _item.title = _item.name;
                _item.key = _item.id
                if (_item.children) {
                    this.initHtree(_item.children)
                }
            }
        }
        this.hztreeData = _tempArr;
    }
    getList() {
        return new Promise((resolve, reject) => {
            try {
                let _dataJson = {
                    createTime: this.dateRange,
                    blurry: this.searchKey
                }
                this.menuManageService.apiList(_dataJson).subscribe(res => {
                    this.listOfMapData = res.content;
                    this.initHtree(this.listOfMapData);
                    resolve(res);
                })
            } catch (e) {
                reject(e);
            }
        })
    }
    collapse(array, data, $event: boolean): void {
        if ($event === false) {
            if (data.children) {
                data.children.forEach(d => {
                    const target = array.find(a => a.id === d.id);
                    target.expand = false;
                    this.collapse(array, target, false);
                });
            } else {
                return;
            }
        }
    }
    convertTreeToList(root) {
        const stack = [];
        const array = [];
        const hashMap = {};
        stack.push({ ...root, level: 0, expand: false });

        while (stack.length !== 0) {
            const node = stack.pop()!;
            this.visitNode(node, hashMap, array);
            if (node.children) {
                for (let i = node.children.length - 1; i >= 0; i--) {
                    stack.push({ ...node.children[i], level: node.level! + 1, expand: false, parent: node });
                }
            }
        }
        return array;
    }
    visitNode(node, hashMap, array): void {
        if (!hashMap[node.id]) {
            hashMap[node.id] = true;
            array.push(node);
        }
    }
    initMapOfExpandedData() {
        this.listOfMapData.forEach(item => {
            this.mapOfExpandedData[item.id] = this.convertTreeToList(item);
        });
    }
    checkAll(value: boolean): void {
        this.deleteIds = [];
        this.mapOfExpandedData.forEach(item => {
            if (item) {
                item.forEach($item => {
                    this.mapOfCheckedId[$item.id] = value
                })
            }
        });
        this.isIndeterminate = false;
        this.filterDelData();
    }
    checkItem(item, id, pid) {
        this.mapOfCheckedId[item.id] = this.mapOfCheckedId[id];
        if (item.children && item.children.length != 0) {
            for (let i = 0; i < item.children.length; i++) {
                this.checkItem(item.children[i], id, pid);
            }
        }
        let _temp = [];
        this.mapOfExpandedData.forEach(item => {
            item.forEach($item => {
                if ($item.pid == pid) {
                    _temp.push($item)
                }
            });
        });
        let _isChecked = true;
        _temp.forEach(item => {
            for (const key in this.mapOfCheckedId) {
                if (!this.mapOfCheckedId[item.id]) {
                    _isChecked = false;
                }
            }
        });
        this.mapOfCheckedId[pid] = _isChecked;

        this.isAllCheck = this.listOfMapData.every(item => {
            return this.mapOfCheckedId[item.id]
        });

        this.isIndeterminate = this.listOfMapData.some(item => {
            return this.mapOfCheckedId[item.id] && !this.isAllCheck
        })

        this.filterDelData();
    }
    filterDelData() {
        this.deleteIds = []
        for (const key in this.mapOfCheckedId) {
            if (this.mapOfCheckedId[key]) {
                this.deleteIds.push(Number(key))
            }
        }
    }
    async handleSearch() {
        await this.getList();
        this.initMapOfExpandedData();
    }
    menuTypeChange(type) {
        let _form = this.menuForm;

        if (type === 0) {
            _form.controls["pid"].clearValidators();
            _form.controls["permission"].clearValidators();
        } else {
            if (_form.controls["pid"].value === 0) {
                _form.controls["pid"].setValue(null)
            }
            _form.controls["pid"].setValidators([Validators.required]);
            _form.controls["permission"].setValidators([Validators.required]);
        }
        if (type === 2) {
            _form.controls["icon"].clearValidators();
            _form.controls["path"].clearValidators();
            _form.controls["sort"].clearValidators();
        } else {
            _form.controls["icon"].setValidators([Validators.required]);
            _form.controls["path"].setValidators([Validators.required]);
            _form.controls["sort"].setValidators([Validators.required]);
        }
    }
    handleDate(ev) {
        this.dateRange = ev.map(item => {
            return moment(item).format("YYYY-MM-DD") + " 00:00:00"
        })
        this.getList();
    }
    handleShowModal(item?): void {
        this.isShowModal = true;

        if (item) {
            if (item == 2) {
                _(this.listOfMapData, this.deleteIds[0], (data) => {
                    item = data
                });
            }
            this.editId = item.id;
            this.menuType = item.type;
            this.menuForm.patchValue({
                icon: item.icon,
                hidden: item.hidden,
                name: item.name,
                path: item.path,
                pid: item.pid,
                sort: item.sort,

                iframe: item.iframe,
                cache: item.cache,
                component: item.component,
                permission: item.permission,
            })
            this.menuTypeChange(item.type);

            this.copyData = [];
            this.copyListData(this.listOfMapData, this.copyData);
            let editHtreeData = this.filterListData(this.copyData, item.id);
            this.initHtree(editHtreeData);

        } else {
            this.menuType = 0;
            this.editId = -1;
            this.menuForm.reset({
                hidden: false,
                iframe: false,
                cache: false,
            });
            this.initHtree(this.listOfMapData);
        }
        function _(data, id, fn) {
            let _item
            if (data.length > 0) {
                for (let i = 0; i < data.length; i++) {
                    if (data[i].id === id) {
                        fn && fn(data[i])
                        return false;
                    } else {
                        if (data[i].children) {
                            _(data[i].children, id, fn)
                        }
                    }
                };
            }
            return _item;
        }
    }
    copyListData(sourceData, copyData) {
        if (sourceData.length > 0) {
            for (let i = 0; i < sourceData.length; i++) {
                copyData[i] = { ...sourceData[i] };
                copyData[i].children = [];
                if (sourceData[i].children) {
                    this.copyListData(sourceData[i].children, copyData[i].children)
                }
            }
        }
    }
    filterListData(arr, menuId: number) {
        if (arr.length > 0) {
            for (let i = 0; i < arr.length; i++) {
                if (arr[i].id === menuId) {
                    arr.splice(i, 1)
                }else{
                    if( arr[i].children ){
                        this.filterListData(arr[i].children, menuId)
                    }
                }
            }
        }
        return arr
    }
    handleDelete() {
        this.modal.confirm({
            nzTitle: "删除提示",
            nzContent: "确定要删除这条数据吗？",
            nzOnOk: () => {
                this.delete(this.deleteIds)
            }
        })

    }
    handleSubmit(): void {
        if (this.editId != -1) {
            this.edit();
        } else {
            this.add();
        }
    }
    handleCancel(): void {
        this.isShowModal = false;
        this.isOkLoading = false;
    }
    edit() {
        let _submitData = {}
        for (const i in this.menuForm.controls) {
            this.menuForm.controls[i].markAsDirty();
            this.menuForm.controls[i].updateValueAndValidity();
            _submitData[i] = this.menuForm.controls[i].value;
        }
        console.log(_submitData)
        if (this.menuForm.status == "VALID") {
            this.isOkLoading = true;
            let _dataJson = {
                ..._submitData,
                type: this.menuType,
                id: this.editId
            }
            this.menuManageService.apiEdit(_dataJson).subscribe(async res => {
                await this.getList();
                this.initMapOfExpandedData();
                this.hztreeData = []
                this.initHtree(this.listOfMapData);
                this.handleCancel();
            })
        }
    }
    add() {
        let _submitData = {}
        let _menuForm = this.menuForm;
        for (const i in _menuForm.controls) {
            _menuForm.controls[i].markAsDirty();
            _menuForm.controls[i].updateValueAndValidity();
            _submitData[i] = _menuForm.controls[i].value
        }
        if (_menuForm.status == "VALID") {
            this.isOkLoading = true;
            let _dataJson = {
                ..._submitData,
                type: this.menuType
            }
            this.menuManageService.apiAdd(_dataJson).subscribe(async res => {
                await this.getList();
                this.initMapOfExpandedData();
                this.handleCancel();
            })
        }
    }
    delete(ids) {
        this.menuManageService.apiDelete(ids).subscribe(async res => {
            await this.getList();
            this.initMapOfExpandedData();
            this.handleCancel();
            this.deleteIds = [];
            this.mapOfCheckedId={};
        })
    }
}
